//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Logging Application Block
//===============================================================================
// License: http://www.codeplex.com/entlibcontrib/Project/License.aspx
// Author: Randy
//===============================================================================

using System.Diagnostics;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;
using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;

namespace EntLibContrib.Logging.TraceListeners
{
	/// <summary>
	/// Performs logging to a file and rolls the output file when either time or size thresholds are
	/// exceeded.
	/// </summary>
	/// <remarks>
	/// Logging always occurs to the configured file name, and when roll occurs a new rolled file name is calculated
	/// by adding the timeStamp pattern to the configured file name.
	/// <para/>
	/// The need of rolling is calculated before performing a logging operation, so even if the thresholds are exceeded
	/// roll will not occur until a new entry is logged.
	/// <para/>
	/// Both time and size thresholds can be configured, and when the first of them occurs both will be reset.
	/// <para/>
	/// The elapsed time is calculated from the creation date of the logging file.
	/// </remarks>
	public class NoGuidRollingFlatFileTraceListener : NoGuidFlatFileTraceListener
	{
		#region Fields
		private StreamWriterRollingHelper rollingHelper;
		private string timeStampPattern;
		private long rollSizeInBytes;
		private RollInterval rollInterval;
		private double revolvingDays;
		private NoGuidRollFileExistsBehavior rollFileExistsBehavior;
		#endregion

		#region Properties
		/// <summary>
		/// Gets the rolling helper.
		/// </summary>
		/// <value>The rolling helper.</value>
		public StreamWriterRollingHelper RollingHelper
		{
			get { return this.rollingHelper; }
		}

		/// <summary>
		/// Gets or sets the time stamp pattern.
		/// </summary>
		/// <value>The time stamp pattern.</value>
		public string TimeStampPattern
		{
			get { return timeStampPattern; }
			set { timeStampPattern = value; }
		}

		/// <summary>
		/// Gets or sets the roll size in bytes.
		/// </summary>
		/// <value>The roll size in bytes.</value>
		public long RollSizeInBytes
		{
			get { return rollSizeInBytes; }
			set { rollSizeInBytes = value; }
		}

		/// <summary>
		/// Gets or sets the roll interval.
		/// </summary>
		/// <value>The roll interval.</value>
		public RollInterval RollInterval
		{
			get { return rollInterval; }
			set { rollInterval = value; }
		}

		/// <summary>
		/// Gets or sets the revolving days.
		/// </summary>
		/// <value>The revolving days.</value>
		public double RevolvingDays
		{
			get { return revolvingDays; }
			set { revolvingDays = value; }
		}

		/// <summary>
		/// Gets or sets the roll file exists behavior.
		/// </summary>
		/// <value>The roll file exists behavior.</value>
		public NoGuidRollFileExistsBehavior RollFileExistsBehavior
		{
			get { return rollFileExistsBehavior; }
			set { rollFileExistsBehavior = value; }
		}
		#endregion

		#region Construction
		/// <summary>
		/// Initializes a new instance of <see cref="NoGuidRollingFlatFileTraceListener"/>
		/// </summary>
		/// <param name="fileName">The filename where the entries will be logged.</param>
		/// <param name="header">The header to add before logging an entry.</param>
		/// <param name="footer">The footer to add after logging an entry.</param>
		/// <param name="formatter">The formatter.</param>
		/// <param name="maxInstances">Max Instances in for loop appending count to file name, where 0 is no max.</param>
		/// <param name="throwMax">Throw Exception if Max Instances reached.</param>
		/// <param name="rollSizeKB">The maxium file size (KB) before rolling.</param>
		/// <param name="timeStampPattern">The date format that will be appended to the new roll file.</param>
		/// <param name="rollFileExistsBehavior">Expected behavior that will be used when the rool file has to be created.</param>
		/// <param name="rollInterval">The time interval that makes the file rolles.</param>
		/// <param name="revolvingDays">The revolving days to increment before overwrite.</param>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2233:OperationsShouldNotOverflow", MessageId = "rollSizeKB*1024")]
		public NoGuidRollingFlatFileTraceListener(string fileName,
			string header,
			string footer,
			ILogFormatter formatter,
			byte maxInstances,
			bool throwMax,
			int rollSizeKB,
			string timeStampPattern,
			NoGuidRollFileExistsBehavior rollFileExistsBehavior,
			RollInterval rollInterval,
			double revolvingDays)
			: base(fileName, header, footer, formatter)
		{
			this.MaxInstances = maxInstances;
			this.ThrowMax = throwMax;
			this.rollSizeInBytes = rollSizeKB * 1024;
			this.timeStampPattern = timeStampPattern;
			this.rollFileExistsBehavior = rollFileExistsBehavior;
			this.rollInterval = rollInterval;
			this.revolvingDays = revolvingDays;

			this.rollingHelper = new StreamWriterRollingHelper(this);
		}
		#endregion

		#region Public Methods
		/// <summary>
		/// Writes trace information, a data object and event information to the file, performing a roll if necessary.
		/// </summary>
		/// <param name="eventCache">A <see cref="TraceEventCache"/> object that contains the current process ID, thread ID, and stack trace information.</param>
		/// <param name="source">A name used to identify the output, typically the name of the application that generated the trace event.</param>
		/// <param name="eventType">One of the <see cref="TraceEventType"/> values specifying the type of event that has caused the trace.</param>
		/// <param name="id">A numeric identifier for the event.</param>
		/// <param name="data">The trace data to emit.</param>
		/// <remarks>
		/// Formatting is only performed if the object to trace is a <see cref="LogEntry"/> and the formatter is set.
		/// </remarks>
		public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
		{
			this.rollingHelper.RollIfNecessary();

			base.TraceData(eventCache, source, eventType, id, data);
		}
		#endregion
	}
}
